package com.wocao.system.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * redis服务类
 *
 * @author sunhao
 * @date 2021/8/14
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Service
@Slf4j
public class RedisService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 功能描述: 组装key<br>
     *
     * @param key    key
     * @param flagId key值
     * @return java.lang.String
     * @author eggg 2021/8/30 9:13
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public String key(String key, String flagId) {
        StringBuilder sb = new StringBuilder();
        return sb.append(key).append(flagId).toString();
    }

    /**
     * 功能描述: 组装key<br>
     *
     * @param key     key
     * @param flagId  key值
     * @param flagId2 key值
     * @return java.lang.String
     * @author eggg 2021/8/30 9:14
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public String key(String key, String flagId, String flagId2) {
        StringBuilder sb = new StringBuilder();
        sb.append(key);
        if (StringUtils.isNotEmpty(flagId)) {
            sb.append(flagId).append(":");
        }
        return sb.append(flagId2).toString();
    }

    /**
     * 功能描述: 组装key<br>
     *
     * @param key     key
     * @param flagId  key值
     * @param flagId2 key值
     * @param flagId3 key值
     * @return java.lang.String
     * @author eggg 2021/8/30 9:15
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public String key(String key, String flagId, String flagId2, String flagId3) {
        StringBuilder sb = new StringBuilder();
        return sb.append(key).append(flagId).append(":").append(flagId2).append(":").append(flagId3).toString();
    }

    /**
     * 功能描述: 对象转json字符串<br>
     *
     * @param object obj
     * @return java.lang.String
     * @author eggg 2021/8/16 9:02
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public String jsonEncode(Object object) {
        if (object == null) {
            return null;
        }
        return JSON.toJSONString(object);
    }

    /**
     * 功能描述: json字符串转对象<br>
     *
     * @param input 字符串
     * @param type  类类型
     * @return T 对象
     * @author eggg 2021/8/16 9:15
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public <T> T jsonDecode(String input, Class<T> type) {
        if (input == null || input.length() == 0) {
            return null;
        }
        return JSON.parseObject(input, type, Feature.OrderedField);
    }

    //==============================以下是String方法======================================

    /**
     * 功能描述: 字符串set方法<br>
     *
     * @param key   key
     * @param value value
     * @author eggg 2021/8/16 9:04
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public void set(final String key, final String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    /**
     * 功能描述: 字符串setex方法<br>
     *
     * @param key   key
     * @param value value
     * @param time  时间
     * @author eggg 2021/8/14 15:44
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public void setex(final String key, final String value, final int time) {
        stringRedisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
    }

    /**
     * 功能描述: 字符串get方法<br>
     *
     * @param key key
     * @return java.lang.String value
     * @author eggg 2021/8/14 15:44
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public String get(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    /**
     * 功能描述: 删除key<br>
     *
     * @param key key
     * @author eggg 2021/8/14 15:59
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public void del(String key) {
        stringRedisTemplate.delete(key);
    }

    /**
     * 功能描述: 对象setex方法<br>
     *
     * @param key    key
     * @param object object
     * @param time   过期时间
     * @author eggg 2021/8/16 9:09
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public void setexBin(final String key, final Object object, final int time) {
        stringRedisTemplate.opsForValue().set(key, jsonEncode(object), time, TimeUnit.SECONDS);
    }

    /**
     * 功能描述: 对象set方法<br>
     *
     * @param key    key
     * @param object object
     * @author eggg 2021/8/16 9:09
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public void setBin(final String key, final Object object) {
        stringRedisTemplate.opsForValue().set(key, jsonEncode(object));
    }

    /**
     * 功能描述: 对象get方法<br>
     *
     * @param key  key
     * @param type 类类型
     * @return T 对象
     * @author eggg 2021/8/16 9:17
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public <T> T getBin(final String key, final Class<T> type) {
        return jsonDecode(stringRedisTemplate.opsForValue().get(key), type);
    }

    /**
     * 功能描述: ttl方法<br>
     *
     * @param key key
     * @return long 过期时间s
     * @author eggg 2021/8/16 9:18
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public long ttl(final String key) {
        return stringRedisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 功能描述: exists方法<br>
     *
     * @param key key
     * @return boolean
     * @author eggg 2021/8/16 9:20
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public boolean exists(final String key) {
        return stringRedisTemplate.hasKey(key);
    }

    /**
     * 功能描述: expire时间<br>
     *
     * @param key  key
     * @param time 过期时间
     * @return boolean
     * @author eggg 2021/8/16 9:21
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public boolean expire(final String key, final int time) {
        return stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
    }

    //==============================以下是HashMap方法======================================

    /**
     * 功能描述: hPutAll方法<br>
     *
     * @param key     key
     * @param hashMap map
     * @param time    过期时间
     * @author eggg 2021/8/16 10:11
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public void hPutAll(final String key, final Map<String, String> hashMap, final int time) {
        stringRedisTemplate.opsForHash().putAll(key, hashMap);
        this.expire(key, time);
    }

    /**
     * 功能描述: hPut方法<br>
     *
     * @param key key
     * @param hk  hk
     * @param hv  hv
     * @author eggg 2021/8/16 10:26
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public void hPut(final String key, final String hk, final String hv) {
        stringRedisTemplate.opsForHash().put(key, hk, hv);
    }

    /**
     * 功能描述: hget方法<br>
     *
     * @param key  key
     * @param mKey mkey
     * @return java.lang.String
     * @author eggg 2021/8/16 10:15
     * @see [相关类/方法]（可选）
     * @since [产品/模块版本]（可选）
     */
    public String hGet(final String key, final String mKey) {
        return (String) stringRedisTemplate.opsForHash().get(key, mKey);
    }

}
